# -*- coding: utf-8 -*-


import re
from metlib.kits import parse_slice_str
from metlib.datetime import T, TD

solar_sat_zh_subset_d = {
    "PT": u"时间序列",
    "PY": u"年统计值",
    "PM": u"月统计值",
    "PD": u"日变化",
    "RY": u"年统计值",
}

solar_sat_varname_d = {
    'daily_total_rad': u'日总辐射量',
    'total_rad': u'年总辐射量',
    'year_total_rad': u'年总辐射量',
    'month_total_rad': u'月总辐射量',
    'summary': u'汇总统计'
}


# 单位
solar_sat_units_d = {
    'daily_total_rad': u'kWh/m²',
    'month_total_rad': u'kWh/m²',
    'total_rad': u'kWh/m²',
    'year_total_rad': u'kWh/m²'
}

# sat中文名
solar_sat_zh_names = {
    'fy2c': u'风云2C',
    'fy2d': u'风云2D',
    'fy2e': u'风云2E',
    'fy2f': u'风云2F',
    'fy2c_cor': u'风云2C(修正)',
    'fy2d_cor': u'风云2D(修正)',
    'fy2e_cor': u'风云2E(修正)',
}

# 变量名
solar_sat_py_sub_varnames = ['total_rad']
solar_sat_py_varnames = ['summary']
solar_sat_pm_varnames = ['month_total_rad']
solar_sat_pd_varnames = ['daily_total_rad']
solar_sat_pt_varnames = solar_sat_pd_varnames
solar_sat_ry_varnames = ['year_total_rad']

solar_sat_suggest_range_d = {
    'daily_total_rad': (0.0, 10.0),
    'year_total_rad': (1000.0, 2300.0)
}

# 推荐色表
solar_sat_cmap_d = {
    'daily_total_rad': 'solar',
    'year_total_rad': 'solar',
}

# 卫星扫描范围和精度
sat_lonlat_range = {
    'fy2c': {
        'min_lon': 45.0,
        'max_lon': 165.0,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20060101',
        'enddt': '20090101',
        'years': ['2006', '2007', '2008'],
        'sat': 'fy2c'
    },
    'fy2d': {
        'min_lon': 26.5,
        'max_lon': 146.5,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20080101',
        'enddt': '20150101',
        'years': ['2008', '2009', '2010', '2011', '2012', '2013', '2014'],
        'sat': 'fy2d'
    },
    'fy2e': {
        'min_lon': 27.0,
        'max_lon': 147.0,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20100101',
        'enddt': '20150101',
        'years': ['2010', '2011', '2012', '2013', '2014'],
        'sat': 'fy2e'
    },
    'fy2f': {
        'min_lon': 52.0,
        'max_lon': 172.0,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20130101',
        'enddt': '20150101',
        'years': ['2013', '2014'],
        'sat': 'fy2f'
    },
    'fy2c_cor': {
        'min_lon': 45.0,
        'max_lon': 165.0,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20060101',
        'enddt': '20090101',
        'years': ['2006', '2007', '2008'],
        'sat': 'fy2c_cor'
    },
    'fy2d_cor': {
        'min_lon': 26.5,
        'max_lon': 146.5,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20080101',
        'enddt': '20120101',
        'years': ['2008', '2009', '2010', '2011'],
        'sat': 'fy2d_cor'
    },
    'fy2e_cor': {
        'min_lon': 27.0,
        'max_lon': 147.0,
        'min_lat': -60.0,
        'max_lat': 60.0,
        'lon_delta': 1.0,
        'lat_delta': 1.0,
        'begdt': '20100101',
        'enddt': '20120101',
        'years': ['2010', '2011'],
        'sat': 'fy2e_cor'
    },
}


def lonlat_in_which_sats(lon, lat):
    sats = []
    for sat, lonlat_range in sat_lonlat_range.iteritems():
        min_lon = lonlat_range['min_lon']
        max_lon = lonlat_range['max_lon']
        min_lat = lonlat_range['min_lat']
        max_lat = lonlat_range['max_lat']
        if min_lon <= lon <= max_lon and min_lat <= lat <= max_lat:
            sats.append(sat)
    # lon, lat不在任何卫星的扫描范围， 则返回None
    if len(sats) == 0:
        return
    return tuple(sats)


def lonlat_to_ij(lon, lat, info):
    min_lon = info.get('min_lon')
    min_lat = info.get('min_lat')
    max_lon = info.get('max_lon')
    max_lat = info.get('max_lat')
    lon_delta = info.get('lon_delta')
    lat_delta = info.get('lat_delta')
    # 在卫星扫描范围内，返回i,j
    # 不在返回None
    if min_lon <= lon <= max_lon and min_lat <= lat <= max_lat:
        i = int(round((lon - min_lon) / lon_delta))
        j = int(round((lat - min_lat) / lat_delta))
    else:
        return
    return i, j


def get_sat_rect(lon1, lat1, lon2, lat2, info):
    min_lon = min(lon1, lon2) - 0.5
    max_lon = max(lon1, lon2) + 1.5
    min_lat = min(lat1, lat2) - 0.5
    max_lat = max(lat1, lat2) + 1.5
    # 卫星扫描经纬度范围
    min_sat_lon = info.get('min_lon')
    max_sat_lon = info.get('max_lon')
    min_sat_lat = info.get('min_lat')
    max_sat_lat = info.get('max_lat')

    # 超出卫星扫描范围
    if min_lon >= max_sat_lon or max_lon <= min_sat_lon \
            or min_lat >= max_sat_lat or max_lat <= min_sat_lat:
        return

    # 在卫星扫描范围内
    lon_start = min_lon if min_lon > min_sat_lon else min_sat_lon
    lon_end = max_lon if max_lon < max_sat_lon else max_sat_lon
    lat_start = min_lat if min_lat > min_sat_lat else min_sat_lat
    lat_end = max_lat if max_lat < max_sat_lat else max_sat_lat

    i1, j1 = lonlat_to_ij(lon_start, lat_start, info)
    i2, j2 = lonlat_to_ij(lon_end, lat_end, info)
    return {
        'i1': i1,
        'j1': j1,
        'i2': i2,
        'j2': j2,
        'sat': info.get('sat', ''),
        'jy_ix': '%s:%s_%s:%s' % (j1, j2, i1, i2)
    }


def get_all_sat_rect(lon1, lat1, lon2, lat2):
    return [get_sat_rect(lon1, lat1, lon2, lat2, sat_lonlat_range.get(sat)) for sat in sat_lonlat_range
            if get_sat_rect(lon1, lat1, lon2, lat2, sat_lonlat_range.get(sat)) is not None]


def parse_solar_sat_uri(uri):
    reg = r'(?P<dataset>[^/]+)/(?P<subset>[^/]+)/(?P<varname>[^/]+)/(?P<time>[^-+Z/]+)(Z?)(?P<timezone>[-+0-9]*)/(?P<jy_ix>[^/]+)$'
    m = re.match(reg, uri)
    if not m:
        raise ValueError('%s is not a proper solar sat uri' % uri)
    result = { field: m.group(field) for field in ['dataset', 'subset', 'varname', 'time', 'jy_ix']}

    time_str = m.group('time')
    timezone_str = m.group('timezone')
    try:
        timezone = int(timezone_str)
    except ValueError:
        timezone = 0

    if ',' in time_str:
        times = time_str.split(',')
        result['times'] = times
        result['timetype'] = 'year_list'
    elif ':' in time_str:
        # dt range
        begdt, enddt, tdelta = parse_slice_str(time_str)
        result['begdt'] = T(begdt)
        result['enddt'] = T(enddt)
        result['tdelta'] = tdelta
        result['timetype'] = 'dtrange'
    elif len(time_str) == 4:
        # year
        begdt = T(time_str + '0101')
        enddt = begdt + TD('1Y')
        result['begdt'] = begdt
        result['enddt'] = enddt
        result['tdelta'] = '1h'
        result['timetype'] = 'year'
    else:
        raise ValueError('%s is not a proper solar sat uri' % uri)

    result['timezone'] = timezone
    result['subset_long'] = {'PT': 'PointTimeseries'}.get(result['subset'], result['subset'])
    jy, ix = result['jy_ix'].split('_')
    # rect
    if ':' in jy:
        jy1, jy2 = [int(j) for j in jy.split(':')]
        ix1, ix2 = [int(i) for i in ix.split(':')]
        result['jy1'] = jy1
        result['jy2'] = jy2
        result['ix1'] = ix1
        result['ix2'] = ix2
        result['look_up_type'] = 'rect'
    else:
        result['jy'] = int(jy)
        result['ix'] = int(ix)
        result['look_up_type'] = 'point'
    return result
